package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * TODO:事务设计：
 *      1.找到具备原子性的业务操作 ： 转出+转入
 *      2.在这之前开启事务
 *      3.业务操作成功提交，失败回滚
 *
 * TODO:一：转账案例引入了事务
 *      1.问题：就是事务操作代码和业务代码耦合了，不利于扩展
 *             （如果还有业务方法需要事务，就还需要再次编写事务代码）
 *      2.解决：AOP
 *          1）AccountService3Impl ： 把AccountService2Impl中事务代码都删除了
 *          2）切面类TxAdvice
 *
 * TODO:二：编程式事务的AOP改造
 *      1.分析spring编程式事务
 *          1）编程式事务：就是通过编写代码方式来实现事务
 *          2）API
 *              i）DataSourceTransactionManager  事务管理器
 *                  a）支持MyBatis框架或者jdbc（如果dao层用的是其他框架，有可能要切换成其他框架的事务管理器）
 *              ii）DefaultTransactionDefinition  事务定义
 *                  a）隔离级别
 *                      4个级别/默认取值跟数据库自身匹配 ISOLATION_DEFAULT
*                   b）只读
 *                      如果增删改，设置false（默认取值）
 *                      如果查询，设置true（效率高）
 *                  c）超时
 *                      默认值是-1, 表示永不超时
 *                  d）事务传播行为
 *              iii）TransactionStatus
 *
 *   TODO:2. 问题：事务切面类TxAdvivce代码冗余
 *          1）除了这些东西可能改变
 *              a）切入点
 *              b）DataSourceTransactionManager  可能改变
 *              c）事务定义（4个常见属性）可能根据业务代码改变
 *          2）其他是不会改变的
 *          3）解决：Spring封装了TxAdvice类，后续要使用事务，只需要声明既可
 *              i）删除
 *                  a）springConfig类的@EnableAspectJAutoProxy
 *                  b）TxAdvice类去掉
 *              ii）添加（声明式事务）
 *                  a）SpringConfig类添加@EnableTransactionManagement --》 开启声明式事务
 *                  b）SpringConfig类声明 DataSourceTransactionManager
 *                  c）在业务方法上 添加注解 @Transactional
 *          4）声明式事务介绍
 *              a）声明式事务是Spring框架关于事务场景基于AOP再次封装
 *              b）@Transactional位置
 *                  在类中方法上，表示这个方法时切入点
 *                  在类上，表示这个类中所有方法都是切入点
 *                  在接口方法上，表示这个接口所有实现方法都是切入点   （常用！！）
 *                  在接口上，就表示这个接口所有实现类方法都是切面类
 *
 */
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao dao;

    /**
     * 注解写到哪，哪个方法就是切入点，并且设置事务定义
     *              在类中方法上，表示这个方法时切入点
     *              在类上，表示这个类中所有方法都是切入点
     *              在接口方法上，表示这个接口所有实现方法都是切入点   （常用！！）
     *              在接口上，就表示这个接口所有实现类方法都是切面类
     */
    /*@Transactional(
            isolation = Isolation.DEFAULT,
            timeout = 10,
            readOnly = false
    )*/
    @Override
    public void transfer(int outId, int inId, double money) {
        //TODO：2.业务操作
        dao.outMoney(outId, money);
        //可能在转账过程中发生意外: 转出执行,转入还未执行
//            int i = 1/0;
        dao.inMoney(inId, money);
    }

    public void transfer2(){
        System.out.println("需要事务的操作！");
    }
}
